// Copyright (c) 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// ---
// Author: Jeffrey Junfeng Pan (panjunfeng@gmail.com)

/*
  Run Frequent Pattern Mining given a list of transactions. Example usage:

  // Step 0 - set your support parameter.
  int min_support_count = 2;

  // Step 1 - Input your transaction data
  vector<vector<string> > raw_data;
  ... input data here ...
  TransactionsMemoryImpl<string> transactions(&raw_data);

  // Step 2 - Build Pattern Tree
  Miner<string> miner("THIS_ITEM_NEVER_EXISTS_IN_TRANSACTIONS");
  miner.BuildTreeByMinSupportCount(&transactions, min_support_count);

  // Step 3 - Mine Pattern Tree
  Itemsets<string> results;
  miner.GetFrequentItemsetByMinSupportCount(min_support_count, &results);

  // Step 4 - Show results. Check class Itemsets for acccessing pattern details.
  cout << results.ToString();

*/

#ifndef FP_GROWTH_MINER_H_
#define FP_GROWTH_MINER_H_

#include "association_rules.h"
#include "common/macros.h"
#include "common/scoped_ptr.h"
#include "pattern_writer.h"
#include "tree.h"

namespace frequent_pattern_mining {

// ------------------------------------------------------------
//                      Declaration
// ------------------------------------------------------------

template <typename T>
class Miner {
 public:

  // Constructor
  explicit Miner(T impossible_item);

  // Destructor
  ~Miner();

  // Build the frequent pattern tree with the given minimal support count
  void BuildTreeByMinSupportCount(Transactions<T>* transactions,
                                  int min_support_count);

  // Build the frequent pattern tree with the given minimal support ratio
  void BuildTreeByMinSupportRatio(Transactions<T>* transactions,
                                  double min_support_ratio);

  // Get frequent itemset with the given minimal support count
  void GetFrequentItemsetByMinSupportCount(int min_support_count,
                                           Itemsets<T>* results);

  // Get frequent itemset with the given minimal support count. Use 'output'
  // for emitting itemsets in their order of generation.
  void GetFrequentItemsetByMinSupportCount(int min_support_count,
                                           PatternWriter<T>* output);

  // Get frequent itemset with the given minimal support ratio
  void GetFrequentItemsetByMinSupportRatio(double min_support_ratio,
                                           Itemsets<T>* results);


  // Get frequent itemset with the given minimal support ratio. Use 'output'
  // for emitting itemsets in their order of generation.
  void GetFrequentItemsetByMinSupportRatio(double min_support_ratio,
                                           PatternWriter<T>* output);

  // Get association rules with the given minimal confidence count
  void GetAssociationRulesByMinConfidenceCount(const Itemsets<T>& itemsets,
                                               int min_confidence_count,
                                               AssociationRules<T>* rules);

  // Get association rules with the given minimal confidence ratio
  void GetAssociationRulesByMinConfidenceRatio(const Itemsets<T>& itemsets,
                                               double min_confidence_ratio,
                                               AssociationRules<T>* rules);

 private:

  scoped_ptr<Tree<T> > tree_;

  DISALLOW_EVIL_CONSTRUCTORS(Miner);
};

// ------------------------------------------------------------
//                      Definition
// ------------------------------------------------------------

// Constructor
template <typename T>
Miner<T>::Miner(T impossible_item)
  : tree_(new Tree<T>(impossible_item)) {
}

// Destructor
template <typename T>
Miner<T>::~Miner() {
}

// Build the frequent pattern tree with the given minimal support count
template <typename T>
void Miner<T>::BuildTreeByMinSupportCount(Transactions<T>* transactions,
                                          int min_support_count) {
  tree_->BuildTree(transactions, min_support_count, -1);
}

// Build the frequent pattern tree with the given minimal support ratio
template <typename T>
void Miner<T>::BuildTreeByMinSupportRatio(Transactions<T>* transactions,
                                          double min_support_ratio) {
  tree_->BuildTree(transactions, -1, min_support_ratio);
}

// Get frequent itemset with the given minimal support count
template <typename T>
void Miner<T>::GetFrequentItemsetByMinSupportCount(int min_support_count,
                                                   Itemsets<T>* results) {
  tree_->GetFrequentItemsets(min_support_count, -1, results);
}

template <typename T>
void Miner<T>::GetFrequentItemsetByMinSupportCount(int min_support_count,
                                                   PatternWriter<T>* output) {
  tree_->GetFrequentItemsets(min_support_count, -1, output);
}

// Get frequent itemset with the given minimal support ratio
template <typename T>
void Miner<T>::GetFrequentItemsetByMinSupportRatio(double min_support_ratio,
                                                   Itemsets<T>* results) {
  tree_->GetFrequentItemsets(-1, min_support_ratio, results);
}

template <typename T>
void Miner<T>::GetFrequentItemsetByMinSupportRatio(double min_support_ratio,
                                                   PatternWriter<T>* output) {
  tree_->GetFrequentItemsets(-1, min_support_ratio, output);
}

// Get association rules with the given minimal confidence count
template <typename T>
void Miner<T>::GetAssociationRulesByMinConfidenceCount(
    const Itemsets<T>& itemsets,
    int min_confidence_count,
    AssociationRules<T>* rules) {
  rules->BuildRules(itemsets, min_confidence_count, -1);
}

// Get association rules with the given minimal confidence ratio
template <typename T>
void Miner<T>::GetAssociationRulesByMinConfidenceRatio(
    const Itemsets<T>& itemsets,
    double min_confidence_ratio,
    AssociationRules<T>* rules) {
  rules->BuildRules(itemsets, 0, -1, -1, min_confidence_ratio);
}

}  // namespace frequent_pattern_mining

#endif  // FP_GROWTH_MINER_H_
